﻿/******************************************************************************
* Copyright (c) 2012 by Phenomblue
* 
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
* 
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
* 
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*****************************************************************************/

(function ($) {

    var numPlayers = 0,
		ytPlayers = {},
		cuedHTMLPlayers = [],
		htmlLoaded = false,
		htmlReady = false;

    $.fn.jTube = function (options) {

        var settings = {
            width: "425",
            height: "356",
            flashParams: { allowScriptAccess: "always", wmode: "window" },
            playerID: "ytPlayer",
            flashAtts: { id: "ytPlayer" },
            preferIFrame: false,
            onPlayerReady: null,
            onStateChange: null,
            onPlaybackQualityChange: null,
            onError: null,
            videoID: null
        };

		function trace(msg) {
			function pad(number, length) {  
				var str = '' + number;
				while (str.length < length) {
					str = '0' + str;
				}
				return str;
			}

			if (msg && (typeof window.console !== 'undefined') && (typeof window.console.log === 'function')) {
				var d = new Date();
				msg = "JTUBE PLUGIN - [" + pad(d.getHours(), 2) + ":" + pad(d.getMinutes(), 2) + ":" + pad(d.getSeconds(), 2) + ":" + pad(d.getMilliseconds(), 4) + "] - " + msg.replace(/[\n\r]/gi, "\n                      - ");
				window.console.log(msg);
			}
		};

        this.each(function () {
            var ytPlayer;
			
			// Check for and apply necessary defaults
            if (options) {
                $.extend(settings, options);
            }
			else {
				trace("ERROR - No options provided - video ID required");
				return;
			}
			
            if (settings.videoID === null) {
                trace("ERROR - videoID cannot be null");
                return;
            }

            // update numPlayers --> create replaceElementID
            numPlayers++;
			settings.replaceElementID = "ytReplaceElement" + numPlayers;
            $(this).attr("id", settings.replaceElementID);

            // set player id if necessary
            if (settings.playerID === "ytPlayer")
                settings.playerID = settings.flashAtts.id = "ytPlayer" + numPlayers;
				
			// create new YouTube Player Instance
			ytPlayer = new YouTubePlayer(settings);
			ytPlayers[settings.playerID] = ytPlayer;
			
			// embed proper player
			if (!settings.preferIFrame) {
				if (swfobject.hasFlashPlayerVersion("10.1"))
					embedFlashPlayer();
				else if (supportsVideo())
					embedIFramePlayer();
				else
					trace("ERROR - browser doesn't support flash or html5 video");
			}
			else {
				if (supportsVideo())
					embedIFramePlayer();
				else if (swfobject.hasFlashPlayerVersion("10.1"))
					embedFlashPlayer();
				else
					trace("ERROR - browser doesn't support flash or html5 video");
			}
			
            function embedFlashPlayer() {
                swfobject.embedSWF("http://www.youtube.com/e/" + settings.videoID + "?enablejsapi=1&playerapiid=" + settings.playerID,
					               settings.replaceElementID, settings.width, settings.height, "8", null, null, 
								   settings.flashParams, settings.flashAtts);
            }
			
            function embedIFramePlayer() {
				if(!htmlLoaded)
				{
					loadHTMLScript();
					cuedHTMLPlayers.push(ytPlayer);
				}
				else if(htmlLoaded && !htmlReady)
					cuedHTMLPlayers.push(ytPlayer);
				else
					self.initHTMLPlayer();
            }
			
			// loads YT HTML5 API Script
			function loadHTMLScript() {
				htmlLoaded = true;
				var tag = document.createElement('script');
				tag.src = "http://www.youtube.com/player_api";
				var firstScriptTag = document.getElementsByTagName('script')[0];
				firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
			}
            
        });
			
		// Initializes an instance of the HTML5 YT Player
		function initHTMLPlayer(ytPlayer) {
			ytPlayer.playerInstance = new YT.Player(ytPlayer.settings.replaceElementID, {
				height: ytPlayer.settings.height,
				width: ytPlayer.settings.width,
				videoId: ytPlayer.settings.videoID,
				events: {
					'onReady': ytPlayer.onPlayerReady,
					'onStateChange': ytPlayer.onStateChange,
					'onPlaybackQualityChange': ytPlayer.onPlaybackQualityChange,
					'onError': ytPlayer.onError
				}
			});
		};
		
		// convenience method to check for video support
		function supportsVideo() {
			return !!document.createElement('video').canPlayType;
		}
		
		// YouTubePlayer Class
		function YouTubePlayer(settingsObj) {
			
			this.playerInstance = null;
			this.settings = settingsObj;
			
			var self = this;
			
			//--------------------------------------------------------------------------
			//
			//  Callbacks
			//
			//--------------------------------------------------------------------------
			
			this.onPlayerReady = function() {
				if (self.settings.onPlayerReady !== null)
                    self.settings.onPlayerReady(self.playerInstance);
			};
			
			// state change handler
			this.onStateChange = function(state) {
				if (self.settings.onStateChange !== null)
                    self.settings.onStateChange(state);
			};

            // quality change handler
            this.onPlaybackQualityChange = function(quality) {
                if (self.settings.onPlaybackQualityChange !== null)
                    self.settings.onPlaybackQualityChange(quality);
            };
			
			 // error handler
            this.onError = function(errorCode) {
                if (self.settings.onError !== null)
                    self.settings.onError(errorCode);
            };
		}
		
		//--------------------------------------------------------------------------
		//
		//  Global YouTube Callbacks
		//
		//--------------------------------------------------------------------------
		
		// player ready handler (JAVASCRIPT API ONLY)
		onYouTubePlayerReady = function(playerID) {
			//grab reference to player if we emded using flash and add event handlers
			var ytPlayer = ytPlayers[playerID],
				playerInstance = $("#" + ytPlayer.settings.flashAtts.id)[0];
			
			// add listeners to instance
			playerInstance.addEventListener("onStateChange", ytPlayer.onStateChange);
            playerInstance.addEventListener("onPlaybackQualityChange", ytPlayer.onPlaybackQualityChange);
            playerInstance.addEventListener("onError", ytPlayer.onError);
			
			// store reference to the instance --> invoke ready method
			ytPlayer.playerInstance = playerInstance;
			ytPlayer.onPlayerReady();
		};

		// iFrame API ready handler
		onYouTubePlayerAPIReady = function() {
			htmlReady = true;
			for(i=0; i<cuedHTMLPlayers.length; ++i)
				initHTMLPlayer(cuedHTMLPlayers[i]);
		};
    };
})(jQuery);